package com.wanghengzhi.girlfriend.rbac.module.account;

import cn.hutool.core.util.IdUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.wanghengzhi.girlfriend.rbac.core.Call;
import com.wanghengzhi.girlfriend.rbac.core.PageWrapper;
import com.wanghengzhi.girlfriend.rbac.module.account.dto.AccountDTO;
import com.wanghengzhi.girlfriend.rbac.module.account.dto.AccountInputDTO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.Predicate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * @author 王潇
 * @since 2021.6.17
 */
@Service
public class AccountService {

    private static final String ID_NOT_EXIST= "id为： %d 的账号不存在！";
    private static final String ACCOUNT_MODIFIED_SUCCESS = "修改账号成功！";
    private static final String ACCOUNT_EXIST = "此账号 %s 已存在！";
    private static final String ADD_ACCOUNT_SUCCESS = "新增账号 %s 成功！";
    /**
     * 账号修改时间间隔
     */
    private static final int ACCOUNT_EDIT_DAYS = 30;
    public static final String ACCOUNT_CAN_NOT_MODIFIED = "账号 %d 天内只能修改一次。上次修改时间：%s！";

    @Autowired
    private AccountRepository accountRepository;

    /**
     * 后台新增用户
     * @param accountInputDTO 注册信息
     */
    public Call add(AccountInputDTO accountInputDTO) {
        String account = accountInputDTO.getAccount();

        Optional<AccountEntity> a = accountRepository.getFirstByAccount(account);
        if (a.isPresent()) {
            return Call.get().ok(false).message(String.format(ACCOUNT_EXIST, account));
        }

        String password = accountInputDTO.getPassword();
        String salt = IdUtil.fastSimpleUUID();
        String digestedPassword = DigestUtil.sha256(password + salt).toString();

        AccountEntity accountEntity = new AccountEntity();
        accountEntity.setAccount(accountInputDTO.getAccount());
        accountEntity.setPassword(digestedPassword);
        accountEntity.setSalt(salt);
        LocalDateTime now = LocalDateTime.now();
        accountEntity.setGmtAccountModified(now);
        accountEntity.setGmtModified(now);
        accountEntity.setGmtCreated(now);

        accountRepository.save(accountEntity);

        return Call.get().ok(true).message(String.format(ADD_ACCOUNT_SUCCESS, account));
    }

    /**
     * 修改账号 只修改account
     * @param accountInputDTO id以及账号
     * @return call
     */
    public Call updateAccount(AccountInputDTO accountInputDTO) {
        Integer id = accountInputDTO.getId();
        Optional<AccountEntity> accountOpt = accountRepository.findById(id);

        if (!accountOpt.isPresent()) {
            return Call.get().ok(false).message(String.format(ID_NOT_EXIST, id));
        }

        AccountEntity account = accountOpt.get();

        // 此处判断距离上一次修改账号是否超过30天，如果没超过，不允许修改。
        LocalDateTime gmtAccountModified = account.getGmtAccountModified();
        LocalDateTime now = LocalDateTime.now();
        boolean after = gmtAccountModified.plusDays(ACCOUNT_EDIT_DAYS).isAfter(now);
        if (after) {
            return Call.get().ok(false).message(String.format(ACCOUNT_CAN_NOT_MODIFIED, ACCOUNT_EDIT_DAYS, gmtAccountModified.toString()));
        }

        account.setAccount(accountInputDTO.getAccount());
        account.setGmtAccountModified(now);
        account.setGmtModified(now);
        
        accountRepository.save(account);

        return Call.get().ok(true).message(ACCOUNT_MODIFIED_SUCCESS);
    }


    /**
     * 分页查询账号列表
     * @param page 页码
     * @param size 数量
     * @param account 账号 模糊查询
     * @return PageWrapper
     */
    @SuppressWarnings("unchecked")
    public PageWrapper<AccountDTO> page(Integer page, Integer size, String account) {
        Pageable pageable = PageWrapper.of(page, size);

        Specification<AccountEntity> specification = (root, criteriaQuery, criteriaBuilder) -> {
            Predicate and = criteriaBuilder.and();
            if (!StringUtils.isEmpty(account)) {
                Predicate account1 = criteriaBuilder.like(root.get("account"), "%" + account + "%");
                and = criteriaBuilder.and(account1);
            }
            return and;
        };

        Page<AccountEntity> jpaPage = accountRepository.findAll(specification, pageable);

        List<AccountEntity> content = jpaPage.getContent();
        if (CollectionUtils.isEmpty(content)) {
            return new PageWrapper<>(jpaPage);
        }

        List<AccountDTO> dtos = new ArrayList<>();
        for (AccountEntity accountEntity : content) {
            AccountDTO accountDTO = new AccountDTO();
            BeanUtils.copyProperties(accountEntity, accountDTO);
            dtos.add(accountDTO);
        }

        PageWrapper<AccountDTO> convent = new PageWrapper<>(jpaPage);
        convent.setContents(dtos);
        return convent;
    }




}
